<!-- 自动滚动组件 -->
<!-- <AutoScroll width="400px" height="250px">
      <div
        v-for="(item, index) in 20"
        :key="index"
        style="padding: 10px; border-bottom: 1px solid #ddd"
      >
        {{ index + 1 }}. 自定义内容
      </div>
    </AutoScroll> -->

<script lang="ts" setup>
import { ref, watch, onUnmounted, type Ref } from "vue";

// 用于保存每个 DOM 元素的上一次滚动位置
const lastScrollTopMap = new Map<HTMLElement, number>();

// 全局定时器（自动滚动）
const intervalId = setInterval(() => {
  for (let [el, lastScrollTop] of lastScrollTopMap.entries()) {
    if (el.getAttribute("auto-scroll-paused") == null) {
      el.scrollTop += props.speed || 3;
      if (el.scrollTop === lastScrollTop) el.scrollTop = 0;
    }
    lastScrollTopMap.set(el, el.scrollTop);
  }
}, 1000 / 10);

// 判断一个 DOM 元素是否仍在页面中
function isDomInPage(el: HTMLElement): boolean {
  let current = el;
  while (current.parentElement) {
    if (current.parentElement instanceof HTMLHtmlElement) return true;
    current = current.parentElement;
  }
  return false;
}

// 清理不在页面上的 DOM 元素
function clean() {
  for (let el of lastScrollTopMap.keys()) {
    if (!isDomInPage(el)) {
      lastScrollTopMap.delete(el);
    }
  }
}

// 组件 Props
const props = defineProps<{
  width?: string;
  height?: string;
  speed?: number;
}>();

const scrollRef = ref<HTMLElement | null>(null);

// 组合式函数：自动滚动
function useAutoScroll(elRef: Ref<HTMLElement | null>) {
  function toggle(isToOn: boolean) {
    if (!elRef.value) return;
    if (isToOn) {
      elRef.value.removeAttribute("auto-scroll-paused");
    } else {
      elRef.value.setAttribute("auto-scroll-paused", "");
    }
  }

  function gotoTop() {
    if (!elRef.value) return;
    elRef.value.scrollTop = 0;
  }

  watch(
    elRef,
    (newEl, oldEl) => {
      if (newEl instanceof HTMLElement) {
        lastScrollTopMap.set(newEl, 0);
        clean();
      }
      if (oldEl instanceof HTMLElement) {
        lastScrollTopMap.delete(oldEl);
      }
    },
    { immediate: true }
  );

  onUnmounted(() => {
    if (scrollRef.value) {
      lastScrollTopMap.delete(scrollRef.value);
    }
  });

  return { toggle, gotoTop };
}
onUnmounted(() => {
  if (intervalId) {
    clearInterval(intervalId);
  }
});

const { toggle, gotoTop } = useAutoScroll(scrollRef);
</script>

<template>
  <div
    ref="scrollRef"
    :style="{
      width: width || '300px',
      height: height || '200px',
      overflowY: 'auto',
      border: '1px solid #ccc',
    }"
    @mouseenter="toggle(false)"
    @mouseleave="toggle(true)"
  >
    <slot>
      <div style="height: 1000px; background: linear-gradient(#fff, #ddd)">
        默认滚动内容
      </div>
    </slot>
  </div>
  <button @click="gotoTop">回到顶部</button>
</template>
